package com.chao.tlias.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * aop类的执行条件，类型
 * 多个切面类时，可以使用@order（）注解 ，指定优先级，数字越小优先级越高
 * '@Around'注解获取连接点信息时，使用的是ProceedingJoinPoint；
 * 其他的注解，获取连接点信息时，使用的是JoinPoint；
 * JoinPoint是ProceedingJoinPoint的父类
 */
@Slf4j
//@Aspect
@Component
public class MyAspect1 {

    @Pointcut("execution(* com.chao.tlias.service.impl.*.*(..))")//切入点表达式
    private void pt(){
    }

    //前置通知，方法执行之前运行
    @Before("pt()")
    public void before(JoinPoint  joinPoint) {
        log.info("MyAspect1 before........");

        //1.获取目标对象
        Object target = joinPoint.getTarget();
        log.info("获取的目标方法是：{}", target);

        //2.获取目标类
        String className = joinPoint.getTarget().getClass().getName();
        log.info("获取的目标类是：{}", className);

        //3.获取目标方法
        String methodName = joinPoint.getSignature().getName();
         log.info("获取的目标方法是：{}", methodName);

        //4.获取目标方法参数
        Object[] args = joinPoint.getArgs();
        log .info("获取的目标方法参数是：{}", Arrays.toString(args));

    }

    //后置通知，方法执行之后运行
    @After("pt()")
    public void after(){
         log.info("MyAspect1 after........");
    }

    //环绕通知，方法执行前后运行
    @Around("pt()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        //原始方法执行之前的逻辑
        log.info("MyAspect1 around before........");

         //原始方法执行
        Object obj = pjp.proceed();

         //原始方法执行之后的逻辑
        log.info("MyAspect1 around after........");
        return obj;
    }

    // 返回通知，方法正常返回之后运行,出现异常不执行
    @AfterReturning("pt()")
    public void afterReturn(){
        log.info("MyAspect1 afterReturn........");
    }

    // 返回通知，方法正常返回之后运行,只有出现异常时才执行
    @AfterThrowing("pt()")
    public void afterThrowing(){
        log.info("MyAspect1 afterThrowing........");
    }
}
